home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / VideoToolbox 96.06.15 / VideoToolboxSources / CreateTrialSnds.c < prev    next >
Text File  |  1995-07-26  |  6KB  |  179 lines

  1. /* CreateTrialSnds.c
  2. Create snd resources for 2afc testing: a "beep" for each presentation,
  3. rightSnd, wrongSnd, and abortSnd for feedback, and a "purr" that I use between 
  4. the presentation and response to indicate to the user that the computer 
  5. is waiting for a response. You can play these sounds by using Apple's SndPlay(), 
  6. or my SndPlay1(), which is in the VideoToolbox. Note that these are proper
  7. resources and are interchangeable with other snd resources, which you can
  8. retrieve by calling GetNamedResource('snd ',"\pSimple Beep"), for example.
  9. You could also use the sound recording capabilities of your Mac to record
  10. spoken words like "right" and "wrong", accessible in the same way.
  11.  
  12. It's ok to call this routine repeatedly, after the first time it has no effect
  13. since it's smart enough to notice that the sounds have already been created.
  14.  
  15. Unlike other routines in VideoToolboxSources, you will probably not use this
  16. routine unaltered. Instead you'll probably modify the code to produce
  17. sounds that suit your own purposes.
  18.  
  19. Note that the sound handles are published as globals. I don't like using globals,
  20. because they make information flow impossible to work out, but in this case
  21. all alternatives seem unreasonably cumbersome.
  22.  
  23. In updating my software from the Sound Driver to the Sound Manager I was
  24. disappointed to discover that the squareWaveSynth supplied by the Sound
  25. Manager doesn't sound at all like the square wave synthesizer of the
  26. Sound Driver. It seems to interpolate, resulting in smoother waveforms that
  27. are inaudible at low frequencies, even if you set the timbre parameter to 255.
  28. E.g. my "purr" is a 22 Hz square wave of which one only hears the clicks at
  29. the transitions, and is thus inaudible after smoothing. Fortunately one can 
  30. recreate the old square wave synthesizer by using the sampledSynth with 
  31. no interpolation, playing from a square wave table, which can be included in the
  32. snd resource. 
  33.  
  34. Note that the beep, which uses the squareWaveSynth, continues playing even while 
  35. interrupts are suspended, e.g. if you were to call SetPriority(7),
  36. whereas the sounds
  37. produced by the sampledSynth pause while interrupts are suspended. This
  38. implies that the sound chip must implement the squareWaveSynth all by itself.
  39. However, the beep never ends as long as the interrupts remain suspended.
  40. The practical consequence of all this is that you can use "beep" to play
  41. sounds simultaneously with stimuli that (for maximum performance) require
  42. suspension of interrupts.
  43. HISTORY:
  44. 4/1/92    dgp extracted it from DoATrial.c
  45. 6/8/95 dgp Made sure that the Mac structs are always 68k aligned.
  46. */
  47. #include "VideoToolbox.h"
  48. //#include <Sound.h>
  49.  
  50. Handle beep=NULL,rightSnd=NULL,wrongSnd=NULL,abortSnd=NULL,purr=NULL;
  51.  
  52. #if PRAGMA_ALIGN_SUPPORTED || __MWERKS__
  53.     #pragma options align=mac68k
  54. #endif
  55. typedef struct {            // A 'snd ' resource of type 1. See Inside Mac VI:22-19.
  56.     short format;            // must equal 1
  57.     short numberOfSynths;    // 1 in this structure
  58.     short synth;
  59.     long synthInitOption;
  60.     short numberOfCommands;
  61.     SndCommand commands[];
  62. } Snd1Resource;
  63. #if PRAGMA_ALIGN_SUPPORTED || __MWERKS__
  64.     #pragma options align=reset
  65. #endif
  66.  
  67. void CreateTrialSnds(void)
  68. {
  69.     Snd1Resource *s;
  70.     SoundHeader **squareWaveTable;
  71.     
  72.     if(beep!=NULL)return;
  73.     
  74.     squareWaveTable=(SoundHeader **)NewHandle(sizeof(SoundHeader)+8);
  75.     if(squareWaveTable==NULL)goto error;
  76.     (*squareWaveTable)->samplePtr=NULL;
  77.     (*squareWaveTable)->length=8;
  78.     (*squareWaveTable)->sampleRate=880*0x10000;    // 880 Hz
  79.     (*squareWaveTable)->loopStart=0;
  80.     (*squareWaveTable)->loopEnd=8;
  81.     (*squareWaveTable)->encode=stdSH;
  82.     (*squareWaveTable)->baseFrequency=57;        // 440 Hz
  83.     (*squareWaveTable)->sampleArea[0]=0;
  84.     (*squareWaveTable)->sampleArea[1]=255;
  85.     (*squareWaveTable)->sampleArea[2]=0;
  86.     (*squareWaveTable)->sampleArea[3]=255;
  87.     (*squareWaveTable)->sampleArea[4]=0;
  88.     (*squareWaveTable)->sampleArea[5]=255;
  89.     (*squareWaveTable)->sampleArea[6]=0;
  90.     (*squareWaveTable)->sampleArea[7]=255;
  91.  
  92.     purr=NewHandle(sizeof(Snd1Resource)+4*sizeof(SndCommand));
  93.     if(purr==NULL)goto error;
  94.     s=(Snd1Resource *)*purr;
  95.     s->format=1;
  96.     s->numberOfSynths=1;
  97.     s->synth=sampledSynth;
  98.     s->synthInitOption=initNoInterp;
  99.     s->numberOfCommands=4;
  100.     s->commands[0].cmd=soundCmd+dataOffsetFlag;
  101.     s->commands[0].param1=0;
  102.     s->commands[0].param2=GetHandleSize(purr);
  103.     s->commands[1].cmd=ampCmd;
  104.     s->commands[1].param1=70;
  105.     s->commands[1].param2=0;
  106.     s->commands[2].cmd=freqCmd;
  107.     s->commands[2].param1=0;
  108.     s->commands[2].param2=1;        // 17 Hz
  109.     s->commands[3].cmd=nullCmd;
  110.     s->commands[3].param1=0;
  111.     s->commands[3].param2=0;
  112.     HLock((Handle)squareWaveTable);
  113.     HandAndHand((Handle)squareWaveTable,purr);    // append squareWaveTable
  114.     DisposeHandle((Handle)squareWaveTable);
  115.     
  116.     abortSnd=purr;
  117.     if(HandToHand(&abortSnd))goto error;
  118.     s=(Snd1Resource *)*abortSnd;
  119.     s->commands[1].cmd=ampCmd;
  120.     s->commands[1].param1=80;
  121.     s->commands[1].param2=0;
  122.     s->commands[2].cmd=freqDurationCmd;
  123.     s->commands[2].param1=2400;
  124.     s->commands[2].param2=69-5*12;    // 27.5 Hz
  125.     s->commands[3].cmd=quietCmd;
  126.     s->commands[3].param1=0;
  127.     s->commands[3].param2=0;
  128.  
  129.     wrongSnd=abortSnd;
  130.     if(HandToHand(&wrongSnd))goto error;
  131.     s=(Snd1Resource *)*wrongSnd;
  132.     s->synthInitOption=0;
  133.     s->commands[1].cmd=ampCmd;
  134.     s->commands[1].param1=100;
  135.     s->commands[1].param2=0;
  136.     s->commands[2].cmd=freqDurationCmd;
  137.     s->commands[2].param1=1200;
  138.     s->commands[2].param2=69-12;    // 880/2 Hz
  139.  
  140.     beep=NewHandle(sizeof(Snd1Resource)+4*sizeof(SndCommand));
  141.     if(beep==NULL)goto error;
  142.     s=(Snd1Resource *)*beep;
  143.     s->format=1;
  144.     s->numberOfSynths=1;
  145.     s->synth=squareWaveSynth;
  146.     s->synthInitOption=0;
  147.     s->numberOfCommands=4;
  148.     s->commands[0].cmd=timbreCmd;
  149.     s->commands[0].param1=20;
  150.     s->commands[0].param2=0;
  151.     s->commands[1].cmd=ampCmd;
  152.     s->commands[1].param1=100;
  153.     s->commands[1].param2=0;
  154.     s->commands[2].cmd=freqDurationCmd;
  155.     s->commands[2].param1=4000;
  156.     s->commands[2].param2=69;        // 880 Hz
  157.     s->commands[3].cmd=quietCmd;
  158.     s->commands[3].param1=0;
  159.     s->commands[3].param2=0;
  160.     
  161.     rightSnd=beep;
  162.     if(HandToHand(&rightSnd))goto error;
  163.     s=(Snd1Resource *)*rightSnd;
  164.     s->commands[0].cmd=timbreCmd;
  165.     s->commands[0].param1=0;
  166.     s->commands[0].param2=0;
  167.     s->commands[1].cmd=ampCmd;
  168.     s->commands[1].param1=100;
  169.     s->commands[1].param2=0;
  170.     s->commands[2].cmd=freqDurationCmd;
  171.     s->commands[2].param1=100;
  172.     s->commands[2].param2=69+12;    // 2*880 Hz
  173.  
  174.     return;
  175.     
  176.     error:
  177.     PrintfExit("Not enough memory. %s line %d\n",__FILE__,__LINE__);
  178. }
  179.